home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / ply15dat.zip / WAKE.C < prev    next >
C/C++ Source or Header  |  1992-02-04  |  6KB  |  218 lines

  1. /* Test file to create a Targa height field for POVRay -- Alexander Enzmann */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include <float.h>
  7.  
  8. #ifndef M_PI
  9. #define M_PI 3.1415926535897932384626
  10. #endif
  11.  
  12. static float **height_buffer, **height_buffer2;
  13. static int GridHeight, GridWidth;
  14.  
  15. static FILE *TargaFile;
  16.  
  17. void
  18. TargaOpen(char *filename, int x, int y)
  19. {
  20.    unsigned char tgaheader[18];
  21.    if ((TargaFile = fopen(filename, "wb")) == NULL) {
  22.       printf("Failed to open Targa file: %s\n", filename);
  23.       exit(1);
  24.       }
  25.    memset(tgaheader, 0, 18);
  26.    tgaheader[2] = 2;
  27.    tgaheader[12] = (unsigned char)(x & 0xFF);
  28.    tgaheader[13] = (unsigned char)((x >> 8) & 0xFF);
  29.    tgaheader[14] = (unsigned char)(y & 0xFF);
  30.    tgaheader[15] = (unsigned char)((y >> 8) & 0xFF);
  31.    tgaheader[16] = 24;
  32.    tgaheader[17] = 0x20;
  33.    fwrite(tgaheader, 18, 1, TargaFile);
  34. }
  35.  
  36. void
  37. TargaWrite(unsigned char r, unsigned char g, unsigned char b)
  38. {
  39.    fputc(b, TargaFile);
  40.    fputc(g, TargaFile);
  41.    fputc(r, TargaFile);
  42. }
  43.  
  44. void
  45. TargaClose()
  46. {
  47.    fclose(TargaFile);
  48. }
  49.  
  50. void
  51. alloc_height_buffers()
  52. {
  53.    int i, j;
  54.    GridHeight = 160;
  55.    GridWidth = 160;
  56.  
  57.    height_buffer = malloc(GridHeight * sizeof(float *));
  58.    height_buffer2 = malloc(GridHeight * sizeof(float *));
  59.    if (height_buffer == NULL || height_buffer2 == NULL) {
  60.       printf("Failed to allocate height buffer\n");
  61.       exit(1);
  62.       }
  63.    for (i=0;i<GridHeight;i++) {
  64.       height_buffer[i] = malloc(GridWidth * sizeof(float));
  65.       height_buffer2[i] = malloc(GridWidth * sizeof(float));
  66.       if (height_buffer[i] == NULL || height_buffer2[i] == NULL) {
  67.          printf("Failed to allocate element %d of height buffer\n", i);
  68.          exit(1);
  69.          }
  70.       for (j=0;j<GridWidth;j++)
  71.          height_buffer[i][j] = 0.0;
  72.       }
  73. }
  74.  
  75. void
  76. clear_temp_buffer()
  77. {
  78.    int i, j;
  79.    for (i=0;i<GridHeight;i++)
  80.       for (j=0;j<GridWidth;j++)
  81.          height_buffer2[i][j] = -10000.0;
  82. }
  83.  
  84. void
  85. add_buffers()
  86. {
  87.    int i, j;
  88.    for (i=0;i<GridHeight;i++)
  89.       for (j=0;j<GridWidth;j++)
  90.          if (height_buffer2[i][j] != -10000.0)
  91.             height_buffer[i][j] = (height_buffer[i][j]+height_buffer2[i][j])/2;
  92. }
  93.  
  94. void
  95. evaluate_wake(int x0, int z0)
  96. {
  97.    float wave_phase, crest_angle;
  98.    float y;
  99.    int x, z;
  100.    float wave_count = 4.0;
  101.    int wave_steps  = 100;
  102.    float phase_delta = 2.0 * M_PI / wave_steps;
  103.    float total_phase = 2.0 * M_PI * wave_count;
  104.    int crest_steps = 180;
  105.    float amplitude = 64.0;
  106.    float wave_x_scale = 3;
  107.    float wave_z_scale = 1.4;
  108.    int step_count = 0;
  109.    float maxy = -1000.0;
  110.    float miny = 1000.0;
  111.    float decay_factor = 0.8; /* Amount of decay by wavelength */
  112.  
  113.    for (wave_phase=0.0;wave_phase<=total_phase;wave_phase+=phase_delta) {
  114.       clear_temp_buffer();
  115. printf("Step %d of %d\r", step_count, (int)(wave_count * wave_steps));
  116.       step_count++;
  117.  
  118.       /* Determine the amplitude of the wave at this phase angle */
  119.       y = amplitude *                          /* Full wave height */
  120.           cos(fmod(wave_phase, 2.0 * M_PI)) *  /* Change with phase angle */
  121.           pow(decay_factor, wave_phase);       /* Decay with distance */
  122.  
  123.       if (y < miny) miny = y;
  124.       if (y > maxy) maxy = y;
  125.  
  126.       /* Steps through the equation for wave crests, generating offsets */
  127.       for (crest_angle=-M_PI/2.0+M_PI/((float)crest_steps);
  128.            crest_angle<M_PI/2.0;
  129.            crest_angle += M_PI / ((float)crest_steps)) {
  130.          x = x0 + wave_x_scale * (float)wave_phase *
  131.              (5 * cos(crest_angle) - cos(3 * crest_angle));
  132.          z = z0 + wave_z_scale * (float)wave_phase *
  133.              (sin(crest_angle) + sin(3 * crest_angle));
  134.          
  135.          /* Add the deflection into the buffer */
  136.          if (x >= 0 && x < GridWidth && z >= -GridWidth/2 && z < GridHeight/2) {
  137.             if (height_buffer2[x][z + GridWidth/2] == -10000.0)
  138.                height_buffer2[x][z + GridWidth/2] = y;
  139.             }
  140.          }
  141.       add_buffers();
  142.       }
  143. printf("Max: %f, Min: %f\n", maxy, miny);
  144. }
  145.  
  146. void
  147. evaluate_wake1(int x0, int z0)
  148. {
  149.    int x, z;
  150.    float xx0, xx1, y, r, t0, t1, theta, wave_phase;
  151.    float k1, k2;
  152.    float wave_number = 1.0;
  153.    float amplitude = 128.0;
  154.    float ship_velocity = 50.0;
  155.    float wave_velocity = 50.0;
  156.    float miny = 10000.0;
  157.    float maxy = -10000.0;
  158.    float decay_factor = 0.8;
  159.    float dist_scale0 = 0.2;
  160.    float dist_scale1 = 0.1;
  161.    
  162.    clear_temp_buffer();
  163.    for (x=1;x<GridHeight;x++) {
  164.       for (z=-GridWidth/2;z<GridWidth/2;z++) {
  165.          xx0 = x - x0;
  166.          xx1 = z - z0;
  167.          theta = atan(xx1 / xx0);
  168.          k1 = cos(theta);
  169.          k2 = sin(theta);
  170.          t0 = xx0 / ship_velocity;
  171.          t1 = fabs(xx1) / wave_velocity;
  172.          if (t1 <= t0) {
  173.             r = sqrt(xx0 * xx0 + xx1 * xx1);
  174.             wave_phase = (k1 * xx0 + k2 * xx1) * dist_scale0;
  175.             /* Determine the amplitude of the wave at this phase angle */
  176.             y = amplitude *        /* Full wave height */
  177.                 cos(wave_phase) *  /* Change with phase angle */
  178.                 pow(decay_factor, r * dist_scale1);  /* Decay with distance */
  179.             if (y < miny) miny = y;
  180.             if (y > maxy) maxy = y;
  181.             height_buffer2[x][z + GridWidth/2] = y;
  182.             }
  183.          }
  184.       }
  185.    add_buffers();
  186. }
  187.  
  188. void
  189. dump_height_buffer()
  190. {
  191.    unsigned char r, g, b;
  192.    float height;
  193.    int y, i, j;
  194.    for (i=0;i<GridHeight;i++) {
  195.       for (j=0;j<GridWidth;j++) {
  196.          height = height_buffer[i][j];
  197.          if (height < -128.0) height = -128.0;
  198.          if (height > 127.0) height = 127.0;
  199.          height += 128.0;
  200.          r = height;
  201.          height -= (float)r;
  202.          g = 0; /* (unsigned char)(256.0 * height); */
  203.          b = 0;
  204.          TargaWrite(r, g, b);
  205.          }
  206.       }
  207. }
  208.  
  209. void
  210. main()
  211. {
  212.    alloc_height_buffers();
  213.    evaluate_wake(0, 0);
  214.    TargaOpen("wave.tga", GridWidth, GridHeight);
  215.    dump_height_buffer();
  216.    TargaClose();
  217. }
  218.